from django.utils.decorators import method_decorator
from django.utils.deprecation import MiddlewareMixin
from PIL import Image, ImageDraw
import urllib
from hashlib import sha256
import base64
import hmac
from qiniu import Auth
from django.shortcuts import render, redirect
# 导包
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
# 导入类视图
from django.views import View

# 导入models
from myapp.models import *
# 导入序列化对象
from .myser import *
import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
# 导入加密库
import hashlib
# 导入图片库
# 绘画库
from PIL import Image, ImageDraw
# 字体库
from PIL import ImageFont
# 图片库
from PIL import Image
# 随机库
import random
# 文件流
import io

import requests

# 导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

# 导入原生sql模块
from django.db import connection

import jwt


# 导入redis数据库
import redis

# 导入时间模块
import time

# 导入公共目录变量
from mydjango.settings import BASE_DIR

# 导包
from django.db.models import Q, F

# 导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

# 导包
import redis
import re

# 定义ip地址和端口
host = '127.0.0.1'
port = 6379

# 定义链接对象
r = redis.Redis(host=host, port=port)


# 自定义中间件判断用户id
class MyMiddleWare(MiddlewareMixin):
    # 请求之前
    def process_request(self, request):
        # uid = request.GET.get('uid')
        # print(uid)
        # token = request.GET.get('token', None)
        # print(token)
        # if token == None:
        #     return HttpResponse('没有带上令牌')
        # decode_jwt = jwt.decode(token, "123", algorithms=['HS256'])
        # if decode_jwt['uid'] != str(uid):
        #     return HttpResponse('你篡改了用户id')
        pass

    # 模板渲染之前
    def process_view(self, request, view_func, view_args, view_kwargs):
        pass

    # 请求之后
    def process_response(self, request, response):
        return response


# 装饰器
# def my_decorator(func):
#     def wrapper(request, *args, **kwargs):
#         print('装饰器被调用')
#         print('请求接口地址是%s' % request.path)
#         return func(request, *args, **kwargs)
#     return wrapper


# # 类装饰器调用
# from django.utils.decorators import method_decorator


# 定义验证码类
class MyCode(View):

    # 定义随机颜色
    def get_random_color(self):
        R = random.randrange(255)
        G = random.randrange(255)
        B = random.randrange(255)
        return (R, B, G)

    # 获取验证码视图
    def get(self, request):
        # 画布
        img_size = (120, 50)
        # 定义画布对象
        image = Image.new('RGB', img_size, 'white')
        # 定义画笔对象
        draw = ImageDraw.Draw(image, 'RGB')
        # 定义随机字符串
        source = '1234567890'
        # 定义容器
        code_str = ''
        # 定义字体
        my_font = ImageFont.truetype(
            font='C:\\Windows\\Fonts\\comic.ttf', size=20)
        for i in range(4):
            # 获取随机颜色
            text_color = self.get_random_color()
            # 获取随机字符串长度下标
            tmp_num = random.randrange(len(source))
            # 获取字符集
            random_str = source[tmp_num]
            # 添加到容器中
            code_str += random_str
            # 将字符串添加到画布中
            draw.text((10+30*i, 20), random_str, text_color,
                      font=my_font)

        # 建立缓存区
        buf = io.BytesIO()

        # 将验证码存储到redis
        r.set('code', code_str)

        # 获取验证码
        redis_code = r.get('code')
        redis_code = redis_code.decode('utf-8')

        # 将验证码存储到session中
        request.session['code'] = code_str

        # 保存图片
        image.save(buf, 'png')
        return HttpResponse(buf.getvalue(), 'image/png')


# md5加密方法
def make_password(mypass):
    # 生成md5对象
    md5 = hashlib.md5()
    # 定义加密对象
    sign_str = mypass
    # 转码
    sign_utf8 = str(sign_str).encode(encoding="utf-8")
    # 加密操作
    md5.update(sign_utf8)
    # 生成密文
    md5_server = md5.hexdigest()
    return md5_server


# 注册接口
class Register(APIView):

    def get(self, request):

        # 接收参数
        username = request.GET.get('username', '未收到用户名')
        password = request.GET.get('password', '未收到密码')
        code = request.GET.get('code', '未收到验证码')

        # 获取redis中的验证码
        redis_code = r.get('code')

        # 转码
        redis_code = redis_code.decode('utf-8')

        # 判断验证码是否正确
        if code != redis_code:
            res = {}
            res['code'] = 405
            res['msg'] = '验证码错误'
            return Response(res)

        # 排重操作
        user = User.objects.filter(username=username).first()

        if user:
            res = {}
            res['code'] = 405
            res['msg'] = '用户已经存在'
            return Response(res)

        # 进行入库操作
        user = User(username=username, password=make_password(
            password))
        # 保存
        user.save()

        # 返回结果
        res = {}
        res['code'] = 200
        res['msg'] = '注册成功'
        return Response(res)


# 登录接口
class Login(APIView):

    def get(self, request):

        # 接收参数
        username = request.GET.get('username', '未收到用户名')
        password = request.GET.get('password', '未收到密码')

        # 查询数据
        user = User.objects.filter(
            username=username, password=make_password(password)).first()

        if user:
            # jwt加密串
            encode_jwt = jwt.encode(
                {'uid': str(user.id)}, '123', algorithm='HS256')
            # 转码
            encode_str = str(encode_jwt, 'utf-8')

            res = {}
            res['msg'] = '登录成功'
            res['username'] = user.username
            res['uid'] = user.id
            res['videoname'] = user.video
            res['token'] = encode_str
            res['type'] = user.typ
            if re.match(r'http://.*?', user.img) == None:
                res['code'] = 200
                res['filename'] = user.img
            else:
                res['code'] = 201
                res['filename'] = user.img
            return Response(res)

        else:
            res = {}
            res['code'] = 405
            res['msg'] = '用户名或者密码错误'
            return Response(res)


# 新浪微博回调
def wb_back(request):

    # 获取code
    code = request.GET.get('code')
    # 定义微博认证地址
    access_token_url = "https://api.weibo.com/oauth2/access_token"

    # 参数
    res = requests.post(
        access_token_url,
        data={

            "client_id": "2636039333",
            "client_secret": "4e2fbdb39432c31dc5c2f90be3afa5ce",
            "grant_type": "authorization_code",
            "code": code,
            "redirect_uri": "http://127.0.0.1:8000/md_admin/weibo"
        })

    # 将res.text强转为json形式
    res = json.loads(res.text)

    # 获取新浪微博用户名称
    # result = requests.get('https://api.weibo.com/2/users/show.json', params={
    #     'access_token': res['access_token'], 'uid': res['uid']
    # })

    # result = json.loads(result.text)

    # print(result)
    # return HttpResponse(result['name'])

    # 是否用新浪登录过
    user = User.objects.filter(username=str(res['uid'])).first()
    sina_id = ''
    user_id = ''

    if user:
        # 代表曾经登录过
        sina_id = user.username
        user_id = user.id
    else:
        # 创建账号
        user = User(username=str(res['uid']), password='', typ=0)
        # 入库
        user.save()

        # 查询用户ID
        user = User.objects.filter(username=str(res['uid'])).first()
        sina_id = str(res['uid'])
        user_id = user.id

    # jwt加密串
    encode_jwt = jwt.encode({'uid': user.id}, '123', algorithm='HS256')
    # 转码
    encode_str = str(encode_jwt, 'utf-8')

    # 跳转操作
    return redirect('http://localhost:8080?sina_id='+str(sina_id)+'&uid='+str(user_id)+'&token='+encode_str+'&type='+str(user.typ))


# 钉钉回调
def ding_back(request):

    # 获取code
    code = request.GET.get("code")

    t = time.time()
    # 时间戳
    timestamp = str((int(round(t * 1000))))
    appSecret = 'ly-AzMKMmCKQP3geaILT_An32kEfKO3HeOtApy5CgKwjytevVZC0WYsT2gxMB160'
    # 构造签名
    signature = base64.b64encode(hmac.new(appSecret.encode(
        'utf-8'), timestamp.encode('utf-8'), digestmod=sha256).digest())
    # 请求接口，换取钉钉用户名
    payload = {'tmp_auth_code': code}
    headers = {'Content-Type': 'application/json'}
    res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature='+urllib.parse.quote(signature.decode(
        "utf-8"))+"&timestamp="+timestamp+"&accessKey=dingoaukgkwqknzjvamdqh", data=json.dumps(payload), headers=headers)

    res_dict = json.loads(res.text)
    ding_name = res_dict['user_info']['nick']

    # 是否用钉钉登录过
    user = User.objects.filter(username=ding_name).first()
    uid = ''
    uname = ''
    if user:

        # 登录过
        uname = user.username
        uid = user.id

    else:

        # 创建用户
        user = User(username=ding_name, password='', typ=0)

        # 保存
        user.save()

        # 查询用户ID
        user = User.objects.filter(username=ding_name).first()
        uname = ding_name
        uid = user.id

    # jwt加密串
    encode_jwt = jwt.encode({'uid': user.id}, '123', algorithm='HS256')
    # 转码
    encode_str = str(encode_jwt, 'utf-8')

    return redirect('http://localhost:8080?uname='+str(uname)+'&uid='+str(uid)+'&token='+encode_str+'&type='+str(user.typ))


# 上传文件视图
class UploadFile(View):
    def get(self, request):
        # 接收参数
        Qiniu_src = request.GET.get('Qiniu_src')
        uid = request.GET.get('uid')

        # 查找用户
        user = User.objects.get(id=uid)
        user.img = Qiniu_src
        user.save()
        return JsonResponse({"code": 200})

    def post(self, request):
        # 接收参数
        file = request.FILES.get('file')
        uid = request.POST.get('uid')

        # 查找用户
        user = User.objects.get(id=uid)
        user.img = file.name
        user.save()

        # 建立文件流对象
        f = open(os.path.join(UPLOAD_ROOT, '',
                              file.name.replace('"', '', 2)), 'wb')
        # 写入
        for chunk in file.chunks():
            f.write(chunk)
        f.close()

        # 导包

        # 生成水印
        # 打开图片
        img = Image.open('./static/upload/'+file.name)

        # 生成画笔对象
        draw = ImageDraw.Draw(img)
        # 修改图片
        draw.text((0, 0), 'QAQ', fill=(76, 234, 124, 180))

        # 查看图片
        # img.show()

        # 存储图片
        img.save('./static/upload/'+file.name)

        # 返回文件名
        return HttpResponse(json.dumps({'filename': file.name}, ensure_ascii=False), content_type='application/json')


# 定义七牛云存储接口
class QiNiu(APIView):
    def get(self, request):
        # 定义密钥
        q = Auth("AoZCd1_Rovnli9x2hIRqT8qYFk4djXI2sHJ3ok-f",
                 "1_q1Kbsj5JbUW4eMxuTazVcyU4b1h1WKd4cYKXxm")

        # 指定上传空间
        token = q.upload_token('upload1234')
        print(token)
        res = {}
        res['token'] = token
        return Response(res)


# 修改密码
def UpdatePassword(request):
    # 接收参数
    Opass = request.GET.get('Opass')
    Npass = request.GET.get('Npass')
    uid = request.GET.get('uid')

    res = {}

    # 查找用户
    user = User.objects.get(id=uid)

    # 判断用户密码是否一致
    if user.password == make_password(Opass):
        # 修改用户密码
        user.password = make_password(Npass)
        # 保存
        user.save()

        res['code'] = 200
        res['msg'] = '修改密码成功，请重新登录'
        return JsonResponse(res)

    else:
        res['code'] = 405
        res['msg'] = '密码错误，请确认是否为本人操作'
        return JsonResponse(res)


# 上传视频
class UploadVideo(View):
    def post(self, request):
        # 接收参数
        uid = request.POST.get('uid')
        video = request.FILES.get('file')

        # 查找用户
        user = User.objects.get(id=int(uid))

        # 建立文件流对象
        f = open(os.path.join(UPLOAD_ROOT, '',
                              video.name.replace('"', '', 2)), 'wb')
        # 写入
        for chunk in video.chunks():
            f.write(chunk)
        f.close()

        user.video = video.name
        user.save()

        res = {}
        res['code'] = 200
        res['msg'] = '上传成功'
        res['videoname'] = video.name
        return JsonResponse(res)


# # 用户信息接口
# class UserInfo(APIView):
#     @method_decorator(my_decorator)
#     def get(self, request):
#         # 获取uid
#         uid = request.GET.get('uid')
#         # 查询用户
#         user = User.objects.get(id=uid)
#         # 序列化对象
#         user_ser = UserSer(user).data

#         return Response(user_ser)
